from django.shortcuts import render, redirect
# 导包
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
# 导入类视图
from django.views import View

SECRET_KEY = 'asdkajk*12+adasd=mmlkvjjxuv'

import json
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView
# 导入加密库
import hashlib
# 导入图片库
# 绘画库
from PIL import ImageDraw
# 字体库
from PIL import ImageFont
# 图片库
from PIL import Image
# 随机库
import random
# 文件流
import io

import requests

# 导入上传文件夹配置
from mydjango.settings import UPLOAD_ROOT
import os

# 导入原生sql模块
from django.db import connection

import jwt

# 导入redis数据库
import redis

# 导入时间模块
import time

# 导入公共目录变量
from mydjango.settings import BASE_DIR

# 导包
from django.db.models import Q, F

# 导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid

from myapp.models import User

from django.utils.deprecation import MiddlewareMixin

from django.http import QueryDict

# 类视图调用
from django.utils.decorators import method_decorator

# 事务操作
from django.db import transaction

# 密码加密
# from django.contrib.auth.hashers import check_password, make_password

# 正则匹配
import re

# 导入时间模块儿
import datetime

from myapp.serializers import UserSer


import hmac
import base64
from hashlib import sha256
import urllib
import json


# 文件上传
class Uploader(View):

    def post(self, request):
        # 接收参数
        file = request.FILES.get("files")
        # uid = request.POST.get('uid')
        # print(uid)

        # # 将文件写入数据库
        # user = User.objects.get(pk=uid)
        # if user:
        #     users = User()
        #     users.img = file
        #     users.save()
        #     print('---------------------------------')
        # else:
        #     return HttpResponse({'上传失败'})

        # 写入文件
        with open(os.path.join(UPLOAD_ROOT,'',file.name),'wb') as f:
            for chunk in file.chunks():
                f.wrice(chunk)

        return HttpResponse(json.dumps({'filename':file.name},ensure_ascii=False),content_type
            ='application/json')



# 定义验证码类
class MyCode(View):

    # 内置类方法
    def get_random_color(self):

        R = random.randrange(255)
        G = random.randrange(255)
        B = random.randrange(255)

        return (R,G,B)

    def get(self, request):

        # 定义画布
        img_size = (120,50)

        # 定义图像对象
        image = Image.new("RGB",img_size,'#BAC3BB')
        # 定义字体
        font_size = ImageFont.truetype('C:/Windows/Fonts/constani.ttf',30)
        # print(font)
        # 定义画笔
        draw = ImageDraw.Draw(image,"RGB")
        # 定义字符串
        source = '0123456789abcdefghgklmnopqrstuvwxyz'
        # 定义容器，用来接收随机字符串
        code_str = ''
        for i in range(4):
            # 获取字符颜色
            text_color = self.get_random_color()
            # 获取随机字符
            tmp_num = random.randrange(len(source))
            random_str = source[tmp_num]
            code_str += random_str
            # 用画笔把验证码画到图片上
            # 参数：xy:坐标，画在哪个位置；text:画的内容；text_color:画什么颜色；font:字体格式
            draw.text((10+25*i,10),random_str,text_color,font=font_size)

        buf = io.BytesIO()
        image.save(buf,'png')

        # 保存验证码
        # request.session['code'] = code_str
        r = redis.Redis()
        r.set('code',code_str)

        return HttpResponse(buf.getvalue(),'image/png')



# 重写加密方法
def make_password(mypass):

    # 生成对象
    md5 = hashlib.md5()
    # 定义加密对象
    sign_str = mypass
    # 转码
    sign_utf8 = str(sign_str).encode(encoding="utf-8")
    # 加密
    md5.update(sign_utf8)
    # 生成密文
    md5_server = md5.hexdigest()

    return md5_server

# print(make_password("123"))


# 用户注册
class Register(APIView):
    def get(self, request):
        # 接收参数
        username = request.GET.get('username', None)
        password = request.GET.get('password', None)
        pwd = request.GET.get('pwd', None)
        phone = request.GET.get('phone', None)
        email = request.GET.get('email', None)
        password2 = make_password(password)

        if not all([username, password, pwd, phone, email]):
            return Response({'message': '请填写完整数据后提交！', 'code': 400})

        # 排重
        user = User.objects.filter(username=username).first()
        if user:
            res = {}
            res['code'] = 405
            res['message'] = '用户已经存在'
            return Response(res)

        if password != pwd:
            return Response({'message': '两次密码不一致', 'code': 400})

        phone_re = re.compile(r'^1(3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8[0-9]|9[0-9])\d{8}$')
        if not re.search(phone_re, phone):
            return Response({'message': '手机号不符合规范', 'code': 400})

        email_re = re.compile(r'^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$')
        if not re.search(email_re, email):
            return Response({'message': '邮箱格式不正确', 'code': 400})

        # 入库
        user = User(username=username, password=password2, phone=phone, email=email)
        user.save()
        return Response({'message': '注册成功', 'code': 200})

        # try:
        #     user = User(username=username, password=password)
        #     user.save()
        #     return Response({'message': '注册成功', 'code': 200})
        # except Exception as e:
        #     print(str(e))
        #     return Response({'message': '用户名已注册', 'code': 405})


# 用户登录
class Login(APIView):
    def get(self, request):
        # 获取数据
        username = request.GET.get('username', None)
        password = request.GET.get('password', None)

        # 检查数据
        user_obj = User.objects.filter(Q(username=username) | Q(phone=username) | Q(email=username)).first()

        if user_obj:
            pwd = check_password(password, user_obj.password)
            if pwd == True:
                return Response({'message': '登录成功', 'code': 200})
            else:
                return Response({'message': '用户名或密码错误', 'code': 400})
        else:
            return Response({'message': '用户不存在', 'code': 400})


# 登录接口
class LoginView(APIView):

    def post(self, request):
        username = request.data.get('username', None)
        password = request.data.get('password', None)
        phone = request.data.get('phone', None)
        email = request.data.get('email', None)
        active = request.data.get('active', None)
        code = request.data.get('code', None)
        
        # code_str = request.session.get('code', None)
        r = redis.Redis()
        code_s = r.get('code')
        code_str = str(code_s,'utf-8')
        print(code_str)


        if code == code_str:
            if active == '0':
                user = User.objects.filter(username=username, password=make_password(password)).first()

                if user:
                    payload = {
                        'exp':int((datetime.datetime.now()+datetime.timedelta(hours=10)).timestamp()),
                        'data':{
                            'uid':user.id,
                            'username':user.username
                        }
                    }
                    encode_jwt = jwt.encode(payload,'SECRET_KEY',algorithm='HS256')
                    encode_str = str(encode_jwt,'utf-8')
                    return Response({'message': '登录成功', 'code': 200,'username':user.username,
                        'token':encode_str,'uid':user.id})
                else:
                    return Response({'message': '用户名或密码错误', 'code': 400})
                
            
            elif active == '1':
                user = User.objects.filter(phone=phone, password=make_password(password)).first()
                if user:

                    payload = {
                        'exp':int((datetime.datetime.now()+datetime.timedelta(hours=10)).timestamp()),
                        'data':{
                            'uid':user.id,
                            'username':user.username
                        }
                    }
                    encode_jwt = jwt.encode(payload,'SECRET_KEY',algorithm='HS256')
                    encode_str = str(encode_jwt,'utf-8')
                    return Response({'message': '登录成功', 'code': 200,'username':user.username,
                        'token':encode_str,'phone':user.phone,'uid':user.id})
                else:
                    return Response({'message': '手机号或密码错误', 'code': 400})


            else:
                user = User.objects.filter(email=email, password=make_password(password)).first()
                if user:

                    payload = {
                        'exp':int((datetime.datetime.now()+datetime.timedelta(hours=10)).timestamp()),
                        'data':{
                            'uid':user.id,
                            'username':user.username
                        }
                    }
                    encode_jwt = jwt.encode(payload,'SECRET_KEY',algorithm='HS256')
                    encode_str = str(encode_jwt,'utf-8')
                    return Response({'message': '登录成功', 'code': 200,'username':user.username,
                        'token':encode_str,'email':user.email,'uid':user.id})
                else:
                    return Response({'message': '邮箱或密码错误', 'code': 400})
        else:
            return Response({'message': '验证码不正确,请重新输入', 'code': 400})

        
    def put(self, request):
        # 获取数据
        pwd = request.data.get('password')
        pwd2 = request.data.get('password2')
        token = request.data.get('token')
        uid = request.data.get('uid')
        username = request.data.get('username')

        # 数据逻辑判断
        # 解密
        decode_token = jwt.decode(token,'SECRET_KEY',algorithm=['HS256'])
        uname = decode_token.get('username',username)
        uuid = decode_token.get('uid',uid)
        
        
        if pwd != pwd2:
            return Response({'message':'两次密码不一致','code':400})

        else:
            user = User.objects.filter(id=uuid,username=uname).update(password=make_password(pwd))

            if user:
                return Response({'message':'修改成功','code':200})
            else:
                return Response({'message':'修改失败','code':400})


    def get(self, request):
        user_list = User.objects.all()
        user_ser = UserSer(user_list,many=True)

        return Response(user_ser.data)



#构造钉钉登录url
def ding_url(request):
    appid = 'dingoaukgkwqknzjvamdqh'
    redirect_uri = 'http://localhost:8000/dingding_back/'

    return redirect('https://oapi.dingtalk.com/connect/qrconnect?appid='+appid+'&response_type=code&scope=snsapi_login&state=STATE&redirect_uri='+redirect_uri)



#构造钉钉回调方法
def ding_back(request):

    #获取code
    code = request.GET.get("code")

    t = time.time()
    #时间戳
    timestamp = str((int(round(t * 1000))))
    appSecret ='ly-AzMKMmCKQP3geaILT_An32kEfKO3HeOtApy5CgKwjytevVZC0WYsT2gxMB160'
    #构造签名
    signature = base64.b64encode(hmac.new(appSecret.encode('utf-8'),timestamp.encode('utf-8'), digestmod=sha256).digest())
    #请求接口，换取钉钉用户名
    payload = {'tmp_auth_code':code}
    headers = {'Content-Type': 'application/json'}
    res = requests.post('https://oapi.dingtalk.com/sns/getuserinfo_bycode?signature='+urllib.parse.quote(signature.decode("utf-8"))+"&timestamp="+timestamp+"&accessKey=dingoaukgkwqknzjvamdqh",data=json.dumps(payload),headers=headers)

    res_dict = json.loads(res.text)
    print(res_dict)
    
    # 判断
    user = User.objects.filter(username=res_dict['user_info']['nick']).first()

    if user:

        return redirect('http://localhost:8080/mylogin_two?uid=' + str(user.id) + "&username=" + user.username)

    else:

        user = User(username=res_dict['user_info']['nick'])
        user.save()
        user_obj = User.objects.filter(username=res_dict['user_info']['nick']).first()

        return redirect('http://localhost:8080/mylogin_two?uid=' + str(user_obj.id) + "&username=" + user_obj.username)




